Popular Searches
Popular Course Categories
Popular Courses

Creating Cards, Toolbars, Navigation Bars, and Tab Bars

Creating Cards, Toolbars, Navigation Bars, and Tab Bars

Apple Human Interface Guidelines and Advanced UI Components

Creating Cards, Toolbars, Navigation Bars, and Tab Bars in iOS

Course: iOS App Development

Topic: Creating Cards, Toolbars, Navigation Bars, and Tab Bars

Course Link: iOS Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction

Cards, toolbars, navigation bars, and tab bars are important UI elements used to organize content and navigation in iOS applications. They help users understand information, access common actions, move between screens, and switch between major sections of an app.

In SwiftUI, these interface elements can be created using views and modifiers such as VStack, HStack, RoundedRectangle, NavigationStack, .toolbar, ToolbarItem, and TabView. UIKit provides equivalent building blocks, including UINavigationController, UIToolbar, and UITabBarController.

For example, a learning app may display course information inside cards, use a navigation bar for the current page title, provide toolbar actions for search or editing, and use a tab bar to switch between Home, Courses, Saved Items, and Profile.

2. Learning Objectives

  • Understand the purpose of cards, toolbars, navigation bars, and tab bars.
  • Create reusable card layouts using SwiftUI.
  • Configure navigation titles and navigation bar actions.
  • Add toolbar buttons and menus with .toolbar.
  • Create tab-based navigation using TabView.
  • Use SF Symbols to improve visual clarity.
  • Manage selected tabs and navigation between screens.
  • Design responsive, accessible, and consistent interfaces.

3. Understanding Cards in iOS

3.1 What Is a Card?

A card is a visual container that groups related information into a distinct section. Cards are useful when an app displays multiple items that users need to scan, compare, or select.

Common examples include course cards, product cards, dashboard summaries, booking details, profile summaries, and news previews.

3.2 Common Card Elements

  • Image or icon: Represents the item or category.
  • Title: Communicates the main subject.
  • Description: Provides supporting information.
  • Metadata: Displays details such as price, duration, rating, or status.
  • Action: Lets the user open details, save an item, or perform another task.

3.3 Benefits of Card-Based Layouts

  • Separate related information into clear groups.
  • Improve readability and visual hierarchy.
  • Make lists of products, courses, or articles easier to scan.
  • Support reusable designs across multiple screens.
  • Allow flexible layouts that adapt to different screen sizes.

4. Creating a Basic Card Using SwiftUI

The following example creates a simple course card using a rounded background, an icon, a title, a description, and an action button.

import SwiftUI

struct CourseCardView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Image(systemName: "book.closed.fill")
                .font(.system(size: 32))
                .foregroundStyle(.blue)

            Text("iOS App Development")
                .font(.headline)

            Text("Learn SwiftUI, navigation, layouts, and app design.")
                .font(.subheadline)
                .foregroundStyle(.secondary)

            Button("View Course") {
                // Open the course details screen.
            }
            .buttonStyle(.borderedProminent)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(Color(.secondarySystemBackground))
        )
        .overlay {
            RoundedRectangle(cornerRadius: 16)
                .strokeBorder(Color.gray.opacity(0.2), lineWidth: 1)
        }
    }
}

#Preview {
    CourseCardView()
        .padding()
}

Explanation

  • VStack arranges card content vertically.
  • Image(systemName:) displays an SF Symbol icon.
  • Text displays the title and description.
  • Button provides an interactive action.
  • .padding() creates space between the content and card edges.
  • RoundedRectangle creates the card's rounded background.
  • .overlay adds a subtle border.
  • Color(.secondarySystemBackground) uses a system background color that adapts to the current appearance.

5. Creating Multiple Cards in a List

When displaying several items, create a reusable card view and place it inside a scrollable layout. This approach avoids duplicating the same layout code for every item.

import SwiftUI

struct Course: Identifiable {
    let id = UUID()
    let title: String
    let description: String
    let icon: String
}

struct CourseListView: View {
    private let courses = [
        Course(
            title: "SwiftUI Fundamentals",
            description: "Build interfaces with declarative views.",
            icon: "swift"
        ),
        Course(
            title: "iOS Navigation",
            description: "Manage screens and navigation flows.",
            icon: "point.topleft.down.curvedto.point.bottomright.up"
        ),
        Course(
            title: "App Interface Design",
            description: "Create clear and accessible layouts.",
            icon: "rectangle.on.rectangle"
        )
    ]

    var body: some View {
        ScrollView {
            LazyVStack(spacing: 16) {
                ForEach(courses) { course in
                    VStack(alignment: .leading, spacing: 10) {
                        Label(course.title, systemImage: course.icon)
                            .font(.headline)

                        Text(course.description)
                            .font(.subheadline)
                            .foregroundStyle(.secondary)
                    }
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding()
                    .background(
                        RoundedRectangle(cornerRadius: 14)
                            .fill(Color(.secondarySystemBackground))
                    )
                }
            }
            .padding()
        }
        .navigationTitle("Courses")
    }
}

ScrollView allows vertical scrolling, while LazyVStack creates items as they are needed for display. ForEach generates one card for each course in the collection.

6. Card Design Best Practices

  • Keep each card focused on one item or one related group of information.
  • Use consistent corner radii, spacing, and typography.
  • Keep descriptions concise and avoid overcrowding.
  • Use shadows sparingly and preserve sufficient contrast.
  • Make interactive controls easy to identify.
  • Provide accessible labels for meaningful images and icon-only actions.
  • Use a button or another appropriate interactive control for actions rather than making a decorative view appear clickable.
  • Test cards with long titles, larger text settings, and different device widths.

7. Understanding Navigation Bars

7.1 What Is a Navigation Bar?

A navigation bar provides context for the current screen and can offer navigation controls and actions. In SwiftUI, a NavigationStack manages navigation, while modifiers such as .navigationTitle() and .toolbar() configure the navigation interface.

A navigation bar commonly contains a screen title, a back button when appropriate, and actions such as Add, Edit, Search, or Save.

7.2 Creating a Navigation Bar

import SwiftUI

struct HomeView: View {
    var body: some View {
        NavigationStack {
            VStack(spacing: 20) {
                Text("Welcome to the App")
                    .font(.title2.bold())

                NavigationLink("Open Profile") {
                    ProfileDetailsView()
                }
            }
            .padding()
            .navigationTitle("Home")
            .navigationBarTitleDisplayMode(.large)
        }
    }
}

struct ProfileDetailsView: View {
    var body: some View {
        Text("Profile Details")
            .navigationTitle("Profile")
            .navigationBarTitleDisplayMode(.inline)
    }
}

Explanation

  • NavigationStack provides a navigation container.
  • .navigationTitle("Home") sets the screen title.
  • .navigationBarTitleDisplayMode(.large) requests a large title when supported by the navigation context.
  • .navigationBarTitleDisplayMode(.inline) uses a compact title style.
  • NavigationLink opens the profile details screen.

8. Adding Toolbar Actions

A toolbar contains controls that perform actions relevant to the current screen. SwiftUI uses the .toolbar modifier and ToolbarItem to add buttons to supported toolbar locations.

import SwiftUI

struct NotesView: View {
    @State private var isEditing = false

    var body: some View {
        NavigationStack {
            Text("Your notes appear here.")
                .padding()
                .navigationTitle("Notes")
                .toolbar {
                    ToolbarItem(placement: .topBarTrailing) {
                        Button {
                            isEditing.toggle()
                        } label: {
                            Label(
                                isEditing ? "Done" : "Edit",
                                systemImage: isEditing ? "checkmark" : "pencil"
                            )
                        }
                    }

                    ToolbarItem(placement: .topBarLeading) {
                        Button {
                            // Perform a screen-specific action.
                        } label: {
                            Image(systemName: "magnifyingglass")
                        }
                        .accessibilityLabel("Search notes")
                    }
                }
        }
    }
}

Common Toolbar Placements

Placement Purpose
.topBarLeading Places an item near the leading side of the top bar.
.topBarTrailing Places an item near the trailing side of the top bar.
.bottomBar Places an item in a bottom toolbar when supported.
.principal Places custom content in the principal toolbar position, often near the title.
.confirmationAction Marks an action as a confirmation action, such as Save or Done.
.cancellationAction Marks an action as a cancellation action, such as Cancel.

Toolbar placements can render differently depending on the platform, navigation container, and operating-system version. Test the layout in the target iOS environment.

9. Creating a Toolbar Menu

When a screen has several related actions, a Menu can group them behind a single button instead of overcrowding the toolbar.

import SwiftUI

struct DocumentView: View {
    var body: some View {
        NavigationStack {
            Text("Document content")
                .padding()
                .navigationTitle("Document")
                .toolbar {
                    ToolbarItem(placement: .topBarTrailing) {
                        Menu {
                            Button("Share", systemImage: "square.and.arrow.up") {
                                // Present the share interface.
                            }

                            Button("Duplicate", systemImage: "plus.square.on.square") {
                                // Duplicate the document.
                            }

                            Button(
                                "Delete",
                                systemImage: "trash",
                                role: .destructive
                            ) {
                                // Confirm and delete the document.
                            }
                        } label: {
                            Image(systemName: "ellipsis.circle")
                        }
                        .accessibilityLabel("More actions")
                    }
                }
        }
    }
}

Use menus for secondary actions. Destructive actions should be clearly identified and, when appropriate, require confirmation before irreversible changes are made.

10. Understanding Tab Bars

10.1 What Is a Tab Bar?

A tab bar lets users switch between major sections of an application. It generally appears at the bottom of an iPhone app and provides a consistent way to access destinations such as Home, Search, Favorites, and Profile.

10.2 When to Use a Tab Bar

  • When an app has several important top-level destinations.
  • When users frequently move between those destinations.
  • When each tab represents a distinct section rather than a single step in a process.
  • When the navigation structure should remain easy to discover.

11. Creating a Tab Bar with TabView

SwiftUI's TabView provides tab-based navigation. Each tab can have its own view, title, and SF Symbol icon.

import SwiftUI

struct MainTabView: View {
    var body: some View {
        TabView {
            HomeTabView()
                .tabItem {
                    Label("Home", systemImage: "house")
                }

            CoursesTabView()
                .tabItem {
                    Label("Courses", systemImage: "book")
                }

            SavedTabView()
                .tabItem {
                    Label("Saved", systemImage: "bookmark")
                }

            ProfileTabView()
                .tabItem {
                    Label("Profile", systemImage: "person.crop.circle")
                }
        }
    }
}

struct HomeTabView: View {
    var body: some View {
        NavigationStack {
            Text("Welcome Home")
                .navigationTitle("Home")
        }
    }
}

struct CoursesTabView: View {
    var body: some View {
        NavigationStack {
            Text("Explore available courses")
                .navigationTitle("Courses")
        }
    }
}

struct SavedTabView: View {
    var body: some View {
        NavigationStack {
            Text("Your saved items")
                .navigationTitle("Saved")
        }
    }
}

struct ProfileTabView: View {
    var body: some View {
        NavigationStack {
            Text("Your profile")
                .navigationTitle("Profile")
        }
    }
}

Explanation

  • TabView contains the app's top-level destinations.
  • .tabItem provides the label and icon for each tab.
  • Label combines text with an SF Symbol.
  • A separate NavigationStack inside each tab can provide independent navigation within that section.
  • Each tab should have a clear purpose and a concise title.

12. Managing the Selected Tab

Use a state variable when the app needs to read or change the selected tab programmatically. Tag each tab with a matching value.

import SwiftUI

enum AppTab: Hashable {
    case home
    case courses
    case profile
}

struct SelectableTabView: View {
    @State private var selectedTab: AppTab = .home

    var body: some View {
        TabView(selection: $selectedTab) {
            Text("Home Screen")
                .tabItem {
                    Label("Home", systemImage: "house")
                }
                .tag(AppTab.home)

            Text("Courses Screen")
                .tabItem {
                    Label("Courses", systemImage: "book")
                }
                .tag(AppTab.courses)

            Text("Profile Screen")
                .tabItem {
                    Label("Profile", systemImage: "person")
                }
                .tag(AppTab.profile)
        }
    }
}

The selection binding keeps the selected tab synchronized with the state variable. This is useful for flows where an action should take the user to a particular section. The example declares the selection state; additional app logic can update it when required.

13. Combining Cards, Navigation Bars, Toolbars, and Tab Bars

These components are often used together. A course browsing app might use a tab bar for major sections, a navigation bar to show the current section title, toolbar buttons for search or filters, and cards to display individual courses.

import SwiftUI

struct CourseItem: Identifiable {
    let id = UUID()
    let title: String
    let subtitle: String
    let icon: String
}

struct CourseBrowserView: View {
    @State private var showingFavorites = false

    private let courses = [
        CourseItem(
            title: "SwiftUI Essentials",
            subtitle: "Build interfaces using SwiftUI",
            icon: "swift"
        ),
        CourseItem(
            title: "Navigation in iOS",
            subtitle: "Organize screens and flows",
            icon: "arrow.left.arrow.right"
        ),
        CourseItem(
            title: "iOS UI Design",
            subtitle: "Create clear user experiences",
            icon: "rectangle.on.rectangle"
        )
    ]

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVStack(spacing: 14) {
                    ForEach(courses) { course in
                        HStack(spacing: 14) {
                            Image(systemName: course.icon)
                                .font(.title2)
                                .foregroundStyle(.blue)
                                .frame(width: 44, height: 44)

                            VStack(alignment: .leading, spacing: 5) {
                                Text(course.title)
                                    .font(.headline)

                                Text(course.subtitle)
                                    .font(.subheadline)
                                    .foregroundStyle(.secondary)
                            }

                            Spacer(minLength: 8)

                            Image(systemName: "chevron.right")
                                .foregroundStyle(.tertiary)
                        }
                        .padding()
                        .background(
                            RoundedRectangle(cornerRadius: 14)
                                .fill(Color(.secondarySystemBackground))
                        )
                    }
                }
                .padding()
            }
            .navigationTitle("Courses")
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        showingFavorites = true
                    } label: {
                        Image(systemName: "heart")
                    }
                    .accessibilityLabel("Show favorites")
                }
            }
            .sheet(isPresented: $showingFavorites) {
                NavigationStack {
                    Text("Your favorite courses")
                        .navigationTitle("Favorites")
                        .toolbar {
                            ToolbarItem(placement: .confirmationAction) {
                                Button("Done") {
                                    showingFavorites = false
                                }
                            }
                        }
                }
            }
        }
    }
}

This example combines a navigation title, a toolbar action, a sheet presentation, and a list of reusable card-like rows. A complete app can connect each row to a course detail screen and load the items from a data source.

14. Difference Between Navigation Bars, Toolbars, and Tab Bars

UI Element Main Purpose Typical Example
Card Groups related content. A course summary with title and description.
Navigation bar Shows screen context and supports hierarchical navigation. A title with a back button.
Toolbar Provides actions relevant to the current screen. Search, Edit, Save, or More.
Tab bar Switches between major app sections. Home, Courses, Saved, and Profile.

15. Accessibility Best Practices

  • Use meaningful text labels for important actions.
  • Add accessibility labels to icon-only buttons.
  • Ensure text and icons have sufficient contrast.
  • Support Dynamic Type and test larger accessibility text sizes.
  • Use consistent and recognizable symbols.
  • Do not rely only on color to distinguish selected, disabled, or error states.
  • Make touch targets large enough for comfortable interaction.
  • Ensure cards that perform actions expose a clear, accessible control.

16. Responsive Design and Appearance

iOS interfaces should adapt to different devices, orientation changes, and appearance settings. Avoid positioning elements with fixed screen coordinates when standard SwiftUI layout containers can handle the layout naturally.

  • Use flexible stacks, grids, and scroll views for content layouts.
  • Use system background and foreground colors where appropriate.
  • Test card layouts with long text and increased font sizes.
  • Check navigation and toolbar behavior on the iOS versions you support.
  • Test tab navigation on different device sizes and platform configurations.
  • Ensure toolbar actions remain understandable if their visual arrangement changes.

17. Common Mistakes and Troubleshooting

Problem Possible Cause Solution
Cards look crowded Too much content or inconsistent spacing. Reduce unnecessary content and standardize spacing.
Navigation title is missing The view is not in the expected navigation context. Check the placement of NavigationStack and title modifiers.
Toolbar action is not visible Unsupported placement or incorrect container setup. Check the toolbar placement and test on the target iOS version.
Tab selection is not synchronized Tab tags do not match the selection type. Use matching tag values and a compatible selection binding.
Icons have no clear meaning Symbols are unfamiliar or lack labels. Choose recognizable SF Symbols and add accessibility labels.
Content is cut off Layout does not account for available space or larger text. Use flexible layouts and test scrolling and Dynamic Type.
Too many toolbar actions All actions are displayed at once. Keep primary actions visible and group secondary actions in a menu.
Tab bar contains too many sections Too many destinations are treated as top-level navigation. Prioritize core destinations and organize secondary content elsewhere.

18. Mini Project: Course Discovery App

Project Goal: Build a small iOS course discovery interface using cards, navigation bars, toolbars, and tab bars.

Project Requirements

  1. Create a Home tab that displays a welcome message and featured course cards.
  2. Create a Courses tab that lists several courses.
  3. Design reusable cards with icons, titles, descriptions, and actions.
  4. Add navigation titles to the major screens.
  5. Add a toolbar action for search, favorites, or filtering.
  6. Create a Saved tab for bookmarked courses.
  7. Create a Profile tab with basic account information.
  8. Use TabView for switching between the main sections.
  9. Use NavigationStack and NavigationLink to open course details.
  10. Make the interface accessible and responsive.

Expected Outcome

After completing this project, learners should understand how to compose common iOS interface elements into a consistent navigation structure and how to reuse card components across multiple screens.

19. Practice Exercises

  • Create a product card containing an image, product name, price, and a Buy button.
  • Create a dashboard card showing a number, a label, and a small icon.
  • Add an Edit button to a navigation bar.
  • Create a toolbar menu with Share, Duplicate, and Delete actions.
  • Create a tab bar with Home, Search, Notifications, and Profile tabs.
  • Use a selection binding to programmatically switch tabs.
  • Place a navigation stack inside each tab and test navigation independently.
  • Improve accessibility by adding labels to all icon-only controls.

20. Interview Questions and Answers

Q1. What is a card in iOS UI design?

Answer: A card is a container that groups related content, such as an image, title, description, metadata, and actions, into a visually distinct section.

Q2. How can you create a card in SwiftUI?

Answer: Combine views such as VStack or HStack with padding, a rounded background shape, and optional border or shadow styling.

Q3. What is the purpose of NavigationStack?

Answer: NavigationStack manages a hierarchy of screens and supports navigation to destinations.

Q4. How do you set a navigation title in SwiftUI?

Answer: Apply the .navigationTitle() modifier to a view inside the relevant navigation context.

Q5. What is the purpose of the toolbar modifier?

Answer: The .toolbar modifier adds actions or custom content to supported toolbar locations, such as the top bar or bottom toolbar.

Q6. What is the difference between a toolbar and a tab bar?

Answer: A toolbar contains actions related to the current screen, while a tab bar switches between the app's major sections.

Q7. What is TabView used for?

Answer: TabView creates an interface for switching between separate views or sections using tabs.

Q8. How can you display icons in tabs?

Answer: Use a Label with an SF Symbol inside the tab's .tabItem modifier.

Q9. Why should card layouts be reusable?

Answer: Reusable cards reduce duplicated code, maintain visual consistency, and make future design changes easier.

Q10. How can you improve the accessibility of toolbar buttons?

Answer: Provide meaningful labels, maintain sufficient contrast and touch-target size, and test with VoiceOver and Dynamic Type.

21. Quick Revision Checklist

  • Cards: Group related content into clear visual sections.
  • NavigationStack: Manage hierarchical screen navigation.
  • Navigation title: Set with .navigationTitle().
  • Toolbar: Add relevant actions using .toolbar and ToolbarItem.
  • Toolbar menu: Group secondary actions with Menu.
  • TabView: Switch between major app sections.
  • Tab item: Configure labels and icons using .tabItem.
  • State: Use a selection binding when the selected tab needs to be controlled.
  • Accessibility: Provide clear labels and support larger text.
  • Responsive design: Test layouts on different devices and appearance settings.

22. Conclusion

Cards, toolbars, navigation bars, and tab bars form the foundation of many iOS application interfaces. Cards organize information, navigation bars show the current screen context, toolbars provide screen-specific actions, and tab bars allow users to move between top-level sections.

SwiftUI makes these components easier to compose using reusable views and modifiers. By following consistent design, accessibility, and navigation practices, developers can build interfaces that are easier to use, maintain, and extend.


Useful Course Links

Previous Next
whatsapp